package com.zwf.service;

import cn.hutool.core.util.StrUtil;
import com.zwf.constant.FileConstant;
import com.zwf.utils.FileContentExtractor;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * Lucene索引服务
 */
@Service
public class LuceneIndexService {
    private final Path indexPath = FileConstant.fullLuceneIndexPath;
    private final Analyzer analyzer;
    private final FileContentExtractor extractor;

    @Autowired
    public LuceneIndexService(Analyzer analyzer, FileContentExtractor extractor) {
        this.analyzer = analyzer;
        this.extractor = extractor;
    }

    /**
     * 创建索引
     */
    @Async
    public void buildIndex(Path dataDir) {
        try {
            FileUtils.deleteDirectory(indexPath.toFile());
            if (!Files.exists(indexPath)) {
                Files.createDirectories(indexPath);
            }
            FSDirectory dir = FSDirectory.open(indexPath);

            IndexWriterConfig config = new IndexWriterConfig(analyzer);
            config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

            try (IndexWriter writer = new IndexWriter(dir, config)) {
                Files.walk(dataDir)
                        .filter(Files::isReadable)
                        .forEach(path -> indexFile(writer, path));
            }
        } catch (IOException e) {
            throw new RuntimeException("创建索引失败：" + e);
        }
    }

    /**
     * 读取索引文件
     */
    public void indexFile(IndexWriter writer, Path path) {
        try {
            String content = extractor.extractContent(path);
            if (StrUtil.isEmpty(content)) {
                // 内容为空，不索引
                return;
            }
            Document doc = new Document();
            doc.add(new StringField("path", path.toString(), Field.Store.YES));
            doc.add(new TextField("fileName", path.getFileName().toString(), Field.Store.YES));
            doc.add(new TextField("content", content, Field.Store.YES));
            doc.add(new StringField("fileType", getFileExtension(path), Field.Store.YES));
            doc.add(new LongPoint("modified", Files.getLastModifiedTime(path).toMillis()));
            writer.addDocument(doc);
        } catch (IOException e) {
            System.err.println("读取索引文件失败：" + path + "------" + e.getMessage());
        }
    }

    /**
     * 更新索引
     */
    public void updateIndex(Path path) throws IOException {
        try {
            Directory dir = FSDirectory.open(path);
            IndexWriterConfig config = new IndexWriterConfig(analyzer);
            config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

            try (IndexWriter writer = new IndexWriter(dir, config)) {
                // 删除旧索引
                Term term = new Term("path", path.toString());
                writer.deleteDocuments(term);

                // 添加新索引
                indexFile(writer, path);

                writer.commit();
            }
        } catch (IOException e) {
            throw new RuntimeException("更新索引失败：" + e);
        }
    }

    private String getFileExtension(Path path) {
        String fileName = path.getFileName().toString();
        int dotIndex = fileName.lastIndexOf(".");
        return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1).toLowerCase();
    }

}
